/**
 * Copyright (c) 2014- 2015 YCY Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.jkwzms.common.web.controller;

import java.io.Serializable;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.ui.Model;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.jkwzms.common.Constants;
import com.jkwzms.common.entity.AbstractEntity;
import com.jkwzms.common.entity.search.Searchable;
import com.jkwzms.common.inject.support.InjectBaseDependencyHelper;
import com.jkwzms.common.pagination.Pagination;
import com.jkwzms.common.service.BaseService;
import com.jkwzms.common.utils.EasyUiMsg;
import com.jkwzms.common.web.Servlets;
import com.jkwzms.common.web.bind.annotation.PageableDefaults;
import com.jkwzms.common.web.controller.permission.PermissionList;

/**
 * 基础CRUD 控制器
 * <p>
 * User: Jack Liang
 * <p>
 * Date: 13-2-23 下午1:20
 * <p>
 * Version:1.0.0
 */
public abstract class BaseCRUDController<M extends AbstractEntity, ID extends Serializable> extends BaseController<M, ID> implements InitializingBean {

    protected BaseService<M, ID> baseService;

    private boolean              listAlsoSetCommonData = false;

    protected PermissionList     permissionList        = null;

    /**
     * 设置基础service
     * 
     * @param baseService
     */
    public void setBaseService(BaseService<M, ID> baseService) {
        this.baseService = baseService;
    }

    /**
     * 列表也设置common data
     */
    public void setListAlsoSetCommonData(boolean listAlsoSetCommonData) {
        this.listAlsoSetCommonData = listAlsoSetCommonData;
    }

    /**
     * 权限前缀：如sys:user 则生成的新增权限为 sys:user:create
     */
    public void setResourceIdentity(String resourceIdentity) {
        if (!StringUtils.isEmpty(resourceIdentity)) {
            permissionList = PermissionList.newPermissionList(resourceIdentity);
        }
    }

    @Override
    public void afterPropertiesSet() {
        InjectBaseDependencyHelper.findAndInjectBaseServiceDependency(this);
        Assert.notNull(baseService, "BaseService required, Class is:" + getClass());
    }

    @RequestMapping(method = RequestMethod.POST)
    @PageableDefaults(sort = "id=desc")
    @ResponseBody
    public Pagination<M> list(@RequestParam("page") int page, @RequestParam("rows") int pageSize,
                              HttpServletRequest request) {
        if (permissionList != null) {
            this.permissionList.assertHasViewPermission();
        }

        Searchable searchable = Searchable.newSearchable();
        searchable.setPage(page - 1, pageSize);
        searchable.addSearchParams(Servlets.getParametersStartingWith(request, Constants.SEARCH_PREFIX));
        
        return baseService.findAll(searchable);
    }

    /**
     * 仅返回表格数据
     * 
     * @param searchable
     * @param model
     * @return
     */
    @RequestMapping(method = RequestMethod.GET, headers = "table=true")
    @PageableDefaults(sort = "id=desc")
    public String listTable(@RequestParam("page") int page, @RequestParam("rows") int pageSize,
                            HttpServletRequest request) {
        Searchable searchable = Searchable.newSearchable();
        searchable.setPage(page, pageSize);
        searchable.addSearchParams(Servlets.getParametersStartingWith(request, Constants.SEARCH_PREFIX));
        list(page, pageSize, request);

        return viewName("listTable");
    }

    @RequestMapping(value = "/view/{id}", method = RequestMethod.GET)
    public String view(Model model, @PathVariable("id") M m) {

        if (permissionList != null) {
            this.permissionList.assertHasViewPermission();
        }

        setCommonData(model);
        model.addAttribute("m", m);
        model.addAttribute(Constants.OP_NAME, "查看");
        return viewName("editForm");
    }

    @RequestMapping(value = "create", method = RequestMethod.GET)
    public String showCreateForm(Model model) {

//        if (permissionList != null) {
//            this.permissionList.assertHasCreatePermission();
//        }

        setCommonData(model);
        model.addAttribute(Constants.OP_NAME, "新增");
        if (!model.containsAttribute("m")) {
            model.addAttribute("m", newModel());
        }
        return viewName("editForm");
    }

    /**
     * 添加
     * 
     * @param model
     * @param m
     * @param result
     * @param redirectAttributes
     * @return
     */
    @RequestMapping(value = "create", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> create(Model model, @Valid @ModelAttribute("m") M m, BindingResult result,
                                      RedirectAttributes redirectAttributes) {

        if (permissionList != null) {
            this.permissionList.assertHasCreatePermission();
        }

        if (hasError(m, result)) {
            return EasyUiMsg.successMsg(false);
        }
        baseService.save(m);
        return EasyUiMsg.successMsg(true);
    }

    @RequestMapping(value = "update/{id}", method = RequestMethod.GET)
    public String showUpdateForm(@PathVariable("id") M m, Model model) {

        if (permissionList != null) {
            this.permissionList.assertHasUpdatePermission();
        }
        setCommonData(model);
        model.addAttribute(Constants.OP_NAME, "修改");
        model.addAttribute("m", m);
        return viewName("editForm");
    }

    @RequestMapping(value = "{id}/update", method = RequestMethod.POST)
    public String update(Model model, @Valid @ModelAttribute("m") M m, BindingResult result,
                         @RequestParam(value = Constants.BACK_URL, required = false) String backURL,
                         RedirectAttributes redirectAttributes) {

        if (permissionList != null) {
            this.permissionList.assertHasUpdatePermission();
        }

        if (hasError(m, result)) {
            return showUpdateForm(m, model);
        }
        baseService.update(m);
        return redirectToUrl(backURL);
    }

    @RequestMapping(value = "{id}/delete", method = RequestMethod.POST)
    public Map<String, Object> delete(@PathVariable("id") M m,
                                      @RequestParam(value = Constants.BACK_URL, required = false) String backURL,
                                      RedirectAttributes redirectAttributes) {
        if (permissionList != null) {
            this.permissionList.assertHasDeletePermission();
        }

        try {
            baseService.delete(m);
            return EasyUiMsg.successMsg(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return EasyUiMsg.successMsg(false);
    }

    @RequestMapping(value = "batch/delete", method = { RequestMethod.GET, RequestMethod.POST })
    public String deleteInBatch(@RequestParam(value = "ids", required = false) ID[] ids,
                                @RequestParam(value = Constants.BACK_URL, required = false) String backURL,
                                RedirectAttributes redirectAttributes) {

        if (permissionList != null) {
            this.permissionList.assertHasDeletePermission();
        }

        baseService.delete(ids);

        redirectAttributes.addFlashAttribute(Constants.MESSAGE, "删除成功");
        return redirectToUrl(backURL);
    }

}
